package cn.bugstack.mybatis.binding;

import cn.bugstack.mybatis.mapping.MappedStatement;
import cn.bugstack.mybatis.mapping.SqlCommandType;
import cn.bugstack.mybatis.session.Configuration;
import cn.bugstack.mybatis.session.SqlSession;

import java.lang.reflect.Method;

/**
 * @description 映射器方法。在MyBatis中，MapperMethod类是用于封装Mapper接口中的方法信息的类。
 * 作用：
 *      MapperMethod类用于描述Mapper接口中的单个方法，并提供了方法的执行功能。
 * 核心方法：
 *      execute(SqlSession sqlSession, Object[] args)：执行Mapper接口中的方法。
 *      convertArgsToSqlCommandParam(Object[] args)：将方法的参数转换为SQL命令的参数。
 * 内部数据结构：
 *      SqlCommand：包含了Mapper方法的SQL命令信息，如SQL语句、参数映射等。
 *      MethodSignature：包含了Mapper方法的签名信息，如方法名、返回类型、参数类型等。
 * 执行流程：
 *      当调用MapperMethod的execute方法时，会根据Mapper方法的签名信息和SQL命令信息执行相应的SQL操作。
 *      首先，根据方法的参数转换为SQL命令的参数。
 *      然后，根据SQL命令执行相应的数据库操作，如查询、插入、更新、删除等。
 *      最后，根据方法的返回类型返回相应的结果。
 * 使用场景：
 *      在MyBatis中，每个Mapper接口对应一个MapperMethod对象，用于执行Mapper接口中定义的方法。
 *      当调用Mapper接口的方法时，实际上是调用了相应的MapperMethod对象的execute方法来执行SQL操作。
 */
public class MapperMethod {

    private final SqlCommand command;

    public MapperMethod(Class<?> mapperInterface, Method method, Configuration configuration) {
        this.command = new SqlCommand(configuration, mapperInterface, method);
    }

    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result = null;
        switch (command.getType()) {
            case INSERT:
                break;
            case DELETE:
                break;
            case UPDATE:
                break;
            case SELECT:
                result = sqlSession.selectOne(command.getName(), args);
                break;
            default:
                throw new RuntimeException("Unknown execution method for: " + command.getName());
        }
        return result;
    }


    /**
     * SqlCommand类用于封装SQL命令的信息。
     */
    public static class SqlCommand {

        // name --> XML中的namespace+id ---> cn.bugstack.mybatis.test.dao.IUserDao.queryUserInfoById
        private final String name; // 命令的名称
        private final SqlCommandType type; // 命令的类型

        /**
         * 构造函数，根据给定的配置、映射接口和方法初始化SQL命令信息。
         *
         * @param configuration MyBatis的配置信息。
         * @param mapperInterface 映射接口，用于获取映射语句。
         * @param method 方法，对应映射接口中的方法，用于获取具体的映射语句名称。
         */
        public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
            // 生成映射语句的名称
            String statementName = mapperInterface.getName() + "." + method.getName();
            // 根据名称获取MappedStatement
            MappedStatement ms = configuration.getMappedStatement(statementName);
            name = ms.getId();       // 设置命令的名称
            type = ms.getSqlCommandType();     // 设置命令的类型
        }

        public String getName() {
            return name;
        }

        public SqlCommandType getType() {
            return type;
        }
    }

}
